#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <signal.h>
#include <stdarg.h>
#include <getopt.h>
#include <iostream>

#include "clk.h"
#include "gpio.h"
#include "dma.h"
#include "pwm.h"

#include "ws2811.h"

#define TARGET_FREQ WS2811_TARGET_FREQ
#define def_IO_pin  12
#define DMA         10
#define LED_COUNT   10
#define STRIP_TYPE            WS2811_STRIP_GRB		// WS2812/SK6812RGB integrated chip+leds
// #define STRIP_TYPE              WS2811_STRIP_GBR		// WS2812/SK6812RGB integrated chip+leds
//#define STRIP_TYPE            SK6812_STRIP_RGBW		// SK6812RGBW (NOT SK6812RGB)
static uint8_t running = 1;
int clear_on_exit = 0;
ws2811_led_t *matrix;

ws2811_t ledstring =
{
    .freq = TARGET_FREQ,
    .dmanum = DMA,
    .channel =
    {
        [0] =
        {
            .gpionum = def_IO_pin,
            .invert = 0, //是否反转输入
            .count = LED_COUNT,
            .strip_type = STRIP_TYPE,//描述: LED 条带的颜色布局，使用 WS2811_STRIP_xxx 常量之一。这些常量定义了 LED 条带的 RGB 颜色顺序。
            .brightness = 255,
        },
        [1] =
        {
            .gpionum = 0,
            .invert = 0,
            .count = 0,
            .brightness = 0,
        },
    },
};

static void ctrl_c_handler(int signum)
{
	(void)(signum);
    running = 0;
}

static void setup_handlers(void)
{
    struct sigaction sa;
    sa.sa_handler = ctrl_c_handler;

    sigaction(SIGINT, &sa, NULL);
    sigaction(SIGTERM, &sa, NULL);
}

void matrix_render(void)
{
    for (size_t i = 0; i < LED_COUNT; i++)
    {
        ledstring.channel[0].leds[i] = matrix[i];
    }
}

void matrix_clear(void)
{
    for (size_t i = 0; i < LED_COUNT; i++)
    {
        matrix[i] = 0;
    }
}

void matrix_update(void)
{
    static int pos = 0;
    if (pos < LED_COUNT)
    {
        matrix[pos++] = 0xFF0000; //变红
    }
    else if (pos < 2 * LED_COUNT)
    {
        matrix[( pos++ % LED_COUNT)] = 0xFF00; //变绿
    }
    else if (pos < 3 * LED_COUNT)
    {
        matrix[( pos++ % (2*LED_COUNT))] = 0xFF; //变蓝
    }
    else
    {
        matrix_clear();
        pos = 0;
    }
    
}



int main(int argc, char *argv[])
{
    ws2811_return_t ret;
    ws2811 led;
    matrix = static_cast<ws2811_led_t*>(malloc(sizeof(ws2811_led_t) * LED_COUNT));
    // matrix = malloc(sizeof(ws2811_led_t) * LED_COUNT); // ws2811_led_t 就是 0xWWRRGGBB

    setup_handlers();

    if ((ret = led.ws2811_init(&ledstring)) != WS2811_SUCCESS)
    {
        fprintf(stderr, "ws2811_init failed: %s\n", led.ws2811_get_return_t_str(ret));
        return ret;
    }

    while (running)
    {
        matrix_update();
        matrix_render();
        if ((ret = led.ws2811_render(&ledstring)) != WS2811_SUCCESS)
        {
            fprintf(stderr, "ws2811_render failed: %s\n", led.ws2811_get_return_t_str(ret));
            break;
        }
        std::cout << "update!" << std::endl;
        // 15 frames /sec
        usleep(1000000);// / 15
    }

    if (clear_on_exit) {
	matrix_clear();
    matrix_render();
	led.ws2811_render(&ledstring);
    }

    led.ws2811_fini(&ledstring);

    printf ("\n");
    return ret;
}